package com.popcap.ant;

import java.io.*;
import java.util.*;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

import com.popcap.util.GameDescriptorHandler;
import com.popcap.widgets.WidgetsConfiguration;

/**
 * GameResourcesTask 
 *
 * Description: An Ant task for creating resource files using the information from an XML game descriptor. 
 * <br/> 
 *
 * @author Plamen Dragozov
 * 
 */
public class GameResourcesTask extends Task
{
	private String handlerClass;
	private String device;
	private String strSymbols;
	private String devicePropertiesFilename;
	private String gameDescriptor;
	private String constantsInterface;
	private String textsType;
	private boolean decompressPNGs;
	private boolean forceDecompression;
	private String resourcesDir;
	private String utilDir;
	private String target;
	private String uiDescriptor;
	
	
	// The method executing the task
	/**
	 * Parses the XML using a H2G2GameDescriptorHandler and writes the resources to files.
	 */
	public void execute() throws BuildException
	{
		FileOutputStream imagesOut = null;
		FileOutputStream palettesOut = null;
		FileOutputStream soundsOut = null;
		FileOutputStream gameDataOut = null;
		FileOutputStream constantsOut = null;
		FileOutputStream fontsOut = null;
		
		try
		{
			// parse device properties
			Properties deviceProperties = new Properties();
			InputStream in = new FileInputStream(devicePropertiesFilename);
			deviceProperties.load(in);
			in.close();

			// parse symbols
			ArrayList symbols = new ArrayList();
			String[] symbolsArray = strSymbols.split(",");
			for (int i = 0; i < symbolsArray.length; i++)
			{
				symbols.add(symbolsArray[i]);
			}

			// parse game xml
			SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
			GameDescriptorHandler handler;
			if(handlerClass != null && handlerClass.trim().length() > 0){
				handler = (GameDescriptorHandler)Class.forName(handlerClass).newInstance();
			}else{
				handler = new GameDescriptorHandler();
			}
			parser.parse(new File(gameDescriptor), handler);

			soundsOut = new FileOutputStream(resourcesDir+"a");
			palettesOut = new FileOutputStream(resourcesDir+"p");
			imagesOut = new FileOutputStream(resourcesDir+"i");
			fontsOut = new FileOutputStream(resourcesDir+"f");
			
            //write scenes replacing the string ids with integers
            gameDataOut = new FileOutputStream(resourcesDir+"s");
            handler.writeGameData(gameDataOut);
			handler.writeResources(device, symbols, deviceProperties, textsType, imagesOut, decompressPNGs,forceDecompression, soundsOut, palettesOut, fontsOut, resourcesDir, utilDir, target);

			File file;
			String name;
			int index;
			
			//write the constants interface
			if("BREW".equalsIgnoreCase(getTarget()))
			{
				file = new File("src/Constants.cpp");
			}					
			else
			{
				file = new File(constantsInterface);	
			}

			constantsOut = new FileOutputStream(file);
			name = file.getName();
			index = name.lastIndexOf('.');
			if(index > 0)
			{
				name = name.substring(0, index);
			}
			handler.writeConstantsInterface(name, constantsOut, deviceProperties);
			WidgetsConfiguration uiConfiguration = new WidgetsConfiguration(uiDescriptor, handler.textsMap, handler.imageDescriptors, handler.m_FontIds);
			
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new BuildException(e);
		}
		finally
		{
			
			try
			{
				if(imagesOut != null)
				imagesOut.close();
				if(palettesOut != null)
				palettesOut.close();
				if(soundsOut != null)
				soundsOut.close();
				if(gameDataOut != null)
				gameDataOut.close();
				if(constantsOut != null)
				constantsOut.close();
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
		}
	}

	/**
	 * @param pngDecompresser The pngDecompresser to set.
	 */
	public void setDecompressPNGs(String decompressPNGs)
	{
		this.decompressPNGs =
			decompressPNGs != null &&
			decompressPNGs.compareToIgnoreCase("true") == 0;
	}

	/**
	 * @param utilDir The utilDir to set.
	 */
	public void setUtilDir(String utilDir)
	{
		if (utilDir == null ||
			utilDir.length() == 0)
		{
			System.out.println("***** MUST SPECIFY UTIL DIR!!! *****");
		}
		this.utilDir = utilDir.replace('\\','/');
		if (!this.utilDir.endsWith("/"))
		{
			this.utilDir = this.utilDir + "/";
		}
	}
	
	/**
	 * @param resourcesDir The resourcesDir to set.
	 */
	public void setResourcesDir(String resourcesDir)
	{
		if (resourcesDir == null ||
			resourcesDir.length() == 0)
		{
			System.out.println("***** MUST SPECIFY RESOURCES DIR!!! *****");
		}
		this.resourcesDir = resourcesDir.replace('\\','/');
		if (!this.resourcesDir.endsWith("/"))
		{
			this.resourcesDir = this.resourcesDir + "/";
		}
	}
	
	/**
	 * @param textsLocale The textsLocale to set.
	 */
	public void setTextsType(String textsLocale)
	{
		this.textsType = textsLocale;
	}
	
	/**
	 * @param gameDescriptor The gameDescriptor to set.
	 */
	public void setGameDescriptor(String gameDescriptor)
	{
		this.gameDescriptor = gameDescriptor;
	}
	
	/**
	 * @param gameDescriptor The gameDescriptor to set.
	 */
	public void setUiDescriptor(String uiDescriptor)
	{
		this.uiDescriptor = uiDescriptor;
	}
	
	/**
	 * @param device The device name
	 */
	public void setDevice(String device)
	{
		this.device = device.toLowerCase();
	}

	/**
	 * @param symbols The symbols to build with
	 */
	public void setSymbols(String symbols)
	{
		this.strSymbols = symbols;
	}

	/**
	 * @param deviceProperties The device properties filename
	 */
	public void setDeviceProperties(String devicePropertiesFilename)
	{
		this.devicePropertiesFilename = devicePropertiesFilename;
	}
	
	/**
	 * @param constantsInterface The constantsInterface to set.
	 */
	public void setConstantsInterface(String constantsInterface)
	{
		this.constantsInterface = constantsInterface;
	}
		
	/**
	 * 
	 * @param handlerClass
	 */
	public void setHandlerClass(String handlerClass)
	{
		this.handlerClass = handlerClass;
	}


	/**
	 * @param forceDecompression the forceDecompression to set
	 */
	public void setForceDecompression(String sForceDecompression)
	{
		this.forceDecompression =
			sForceDecompression != null &&
			sForceDecompression.compareToIgnoreCase("true") == 0;
	}

	/**
	 * @return the target
	 */
	public String getTarget()
	{
		return this.target;
	}

	/**
	 * @param target the target to set
	 */
	public void setTarget(String target)
	{
		this.target = target;
	}
}